package compilador;

import compilador.lexico.AnalisadorLexico;
import compilador.lexico.LeitorEntrada;
import compilador.sintatico.AnalisadorSintatico;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

/**
 * Classe principal, inicia a execução do programa.
 *
 * @author Carlos H V Pinto
 * @author Lucas S Bueno
 */
public class Main {

    public static void main(String[] args) {

        // Verifica se o programa foi iniciado com pelo menos 2 parâmetros
        if (args.length < 2) {
            System.err.println("Programa com poucos parâmetros");
            System.err.println("Uso: java -jar compilador-la.jar <arquivo_entrada> <arquivo_saida>");
            return;
        }

        InputStream entrada = null;
        PrintStream saida = null;        

        try {
            // Cria os fluxos de entrada e saída em arquivo
            entrada = new FileInputStream(args[0]);
            saida = new PrintStream(new FileOutputStream(args[1]));
        } catch (FileNotFoundException erro) {
            System.err.println("O arquivo de entrada " + args[0] + " não foi encontrado.");
        }
        
        // Guarda os valores de entrada e saída defaults para caso tenham que ser restaurados
        InputStream defaultInput = System.in;
        PrintStream defaultOutput = System.out;

        // Redefine entrada e saída padrão para os arquivos de entrada e saída especificados pelo usuário
        System.setIn(entrada);
        System.setOut(saida);
        System.setErr(saida);

        // Cria o gerenciador de leitor de arquivo e os analisadores 
        LeitorEntrada leitor = new LeitorEntrada();
        AnalisadorLexico lexico = new AnalisadorLexico(leitor);
        AnalisadorSintatico sintatico = new AnalisadorSintatico(lexico);

        // Inicia a análise sintática recursiva preditiva à esquerda
        sintatico.iniciaAnalise();

        // Restaura a entrada e saída padrão
        System.setIn(defaultInput);
        System.setOut(defaultOutput);
        System.setErr(defaultOutput);

        // Fecha os fluxos de entrada e saída dos arquivos
        try {
            entrada.close();
            saida.close();
        } catch (IOException erro) {
            System.err.println("Erro fechando o fluxo de entrada e saída.");
        }
        
        // Exibe uma mensagem que a compilação terminou
        System.out.println("A análise sintática do arquivo " + args[0] + " terminou. "
                + "Veja a saída gerada em " + args[1]);
    }
}
